

function randomMine(game) {
    let mines = [];
    let exsited = {};
    for (let i = 0; i < game.NumOfMines; i++) {
        while (true) {
            let rowIdx = Math.floor(Math.random() * game.nROWS);
            let colIdx = Math.floor(Math.random() * game.nCols);
            let key = `${rowIdx}, ${colIdx}`;
            if (key in exsited) {
                continue;
            }

            mines.push([rowIdx, colIdx]);
            exsited[key] = true;
            break;
        }

    }

    game.mines = mines;

}



function handleClick(game, rowIdx, colIdx) {
    if(game.state === 0){
        
        startingGame(game);
    }

    if(game.state === 2 || game.state === 3){
        return;
    }


    let { nROWS, nCols, cells } = game;

    let cell = cells[rowIdx][colIdx];

    if (cell.flag) {
        cell.flag = false;
        cell.el.classList.remove("flag");
        return;
    }

    if (cell.value == -1) {
        cell.el.classList.add("explode");
        loseGame(game);

    } else if (cell.value > 0) {
        openCell(cell);
    } else if (cell.value == 0) {
        clearSafeArea(game, rowIdx, colIdx);
    }
    checkWin(game);
}

function openCell(cell){
    cell.open = true;
    cell.el.classList.add("open");
}

function winGame(game){
    game.state = 2;
    clearInterval(game.intervalId);
    let el = document.querySelector(".game-info > .status");
    el.innerText = "WIN!!";

    openALLCells(game);
}

function loseGame(game){
    game.state = 3;

    clearInterval(game.intervalId);

    let el = document.querySelector(".game-info > .status");
    el.innerText = "LOSS";

    openALLCells(game);

}

function openALLCells(game){
    let {cells, nROWS, nCols} = game;
    let clearNum = 0;
    let untouchedNum = 0;
    for (let rowIdx = 0; rowIdx < nROWS; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];
            if (!cell.open){
                openCell(cell);
            }     
        }
    }
}

function startingGame(game){
    game.state = 1;

    game. intervalId = setInterval(() => {
        game.elapsed =game.elapsed + 1;
        refreshTimer(game);
    }, 1000);
}

function showRemainNum(game){
    let remainingDiv = document.querySelector(".game-info > .remaining")
    remainingDiv.innerText = game.remainingNum;
}

function refreshTimer(game){
    let el = document.querySelector(".game-info > .timer")
    el.innerText = game.elapsed;
}

function handleFlagCell(game, rowIdx, colIdx) {
    let { nROWS, nCols, cells } = game;

    if(game.state === 0){
        startingGame(game);
    }

    if(game.state === 2 || game.state === 3){
        return;
    }



    let cell = cells[rowIdx][colIdx];
    if (cell.open) {
        return;
    }

    if (cell.flag) {
        cell.flag = false;
        cell.el.classList.remove("flag");
        game.remainingNum = game.remainingNum + 1;
        showRemainNum(game);
    } else {
        if (game.remainingNum > 0){
            cell.flag = true;
            cell.el.classList.add("flag");
            game.remainingNum = game.remainingNum - 1;
            showRemainNum(game);
        }
    }

    checkWin(game);
}

function checkWin(game){
    let {cells, nROWS, nCols} = game;
    let clearNum = 0;
    let untouchedNum = 0;
    for (let rowIdx = 0; rowIdx < nROWS; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];
            if(cell.flag && cell.value == -1){
                clearNum =clearNum + 1;
            }

            if (!cell.open){
                untouchedNum = untouchedNum + 1;
            }

        }
    }

    if (clearNum === game.NumOfMines  || untouchedNum === game.NumOfMines){
        winGame(game);
        return;
    }

}

function clearSafeArea(game, rowIdx, colIdx) {
    let { nROWS, nCols, cells } = game;

    let cell = cells[rowIdx][colIdx];
    if (cell.value != 0) {
        return;
    }
    cell.open = true;
    cell.el.classList.add("open");


    for (let [deltaRow, deltaCol] of direction) {
        let newCol = colIdx + deltaCol;
        let newRow = rowIdx + deltaRow;
        if (newRow < 0 || newRow >= nROWS) {
            continue;
        }
        if (newCol < 0 || newCol >= nCols) {
            continue;
        }


        let neighborCell = cells[newRow][newCol];

        if (neighborCell.open || neighborCell.flag) {
            continue;
        }

        if (neighborCell.value > 0) {
            neighborCell.open = true;
            neighborCell.el.classList.add("open");
            continue;
        }

        if (neighborCell.value == 0) {
            clearSafeArea(game, newRow, newCol);
        }


    }

}


function countSurroundingMines(game) {

    let { nROWS, nCols, cells } = game;

    for (let rowIdx = 0; rowIdx < nROWS; rowIdx++) {
        for (let colIdx = 0; colIdx < nCols; colIdx++) {
            let cell = cells[rowIdx][colIdx];
            if (cell.value == -1) {
                continue;
            }



            let numMines = 0;
            for (let [deltaRow, deltaCol] of direction) {
                let newCol = colIdx + deltaCol;
                let newRow = rowIdx + deltaRow;
                if (newRow < 0 || newRow >= nROWS) {
                    continue;
                }
                if (newCol < 0 || newCol >= nCols) {
                    continue;
                }

                let neighborCell = cells[newRow][newCol];

                if (neighborCell.value == -1) {
                    numMines++;
                }

            }

            cell.value = numMines;
            if (numMines == 1) {
                cell.el.classList.add("warn-1");
            } else if (numMines == 2) {
                cell.el.classList.add("warn-2");
            } else if (numMines > 2) {
                cell.el.classList.add("warn-3");
            }

            if (numMines > 0) {
                //document.querySelector()
                let mineEL = cell.el.querySelector(".mine");
                mineEL.innerText = numMines;
                //cell.el.innerText = numMines;
            }


        }
    }


}


function main() {
    console.log("main")

    let game = {
        nROWS: 9,
        nCols: 9,
        NumOfMines: 10,
        elapsed: 0,
        
        state: 0, //0: ready, 1: running, 2: win, 3: lose
        drawgrid: function () {
            let tblel = document.querySelector("#gameboard > table.mine-grid");
            console.log(tblel);
            let cells = [];
            for (let rowIdx = 0; rowIdx < this.nROWS; rowIdx++) {
                let trEl = document.createElement("tr");
                let cellrow = [];
                for (let colIdx = 0; colIdx < this.nCols; colIdx++) {
                    let tdEl = document.createElement("td");

                    let cellDiv = document.createElement("div");
                    cellDiv.className = "cell";

                    cellDiv.innerHTML = `<div class="mine"></div><div class="flag">&#128681</div>`

                    cellDiv.addEventListener("click", (e) => {
                        console.log("click:", colIdx, rowIdx);
                        handleClick(game, rowIdx, colIdx);
                    });

                    cellDiv.addEventListener("contextmenu", (e) => {
                        e.preventDefault();
                        handleFlagCell(game, rowIdx, colIdx);
                    })


                    tdEl.append(cellDiv);
                    trEl.append(tdEl);

                    cellrow.push({
                        open: false,
                        el: cellDiv,
                    })
                }

                cells.push(cellrow);

                tblel.append(trEl);//

            }

            //h绘制雷
            for (let mine of this.mines) {
                let [rowIdx, colIdx] = mine;

                let cell = cells[rowIdx][colIdx];
                cell.value = -1; // 有雷设置-1，没有雷此值表示周边雷数

                let mineEL = cell.el.querySelector(".mine");
                mineEL.innerHTML = "&#128163;"
            }
            this.cells = cells;

            showRemainNum(game);
            refreshTimer(game);
        }
    };

    game.remainingNum = game.NumOfMines;



    
    randomMine(game);
    game.drawgrid()
    countSurroundingMines(game);

}

function showRemainNum(game){
    let remainingDiv = document.querySelector(".game-info > .remaining")
    remainingDiv.innerText = game.remainingNum;
}

let direction = [
    [-1, -1],
    [-1, 0],
    [-1, 1],
    [0, -1],
    [0, 1],
    [1, -1],
    [1, 0],
    [1, 1],
]



let mock_mines = [
    [
        1,
        1
    ],
    [
        5,
        8
    ],
    [
        3,
        6
    ],
    [
        5,
        7
    ],
    [
        8,
        1
    ],
    [
        3,
        4
    ],
    [
        7,
        5
    ],
    [
        8,
        6
    ],
    [
        1,
        3
    ],
    [
        0,
        0
    ]
]